Work in progress Programmation Web
En prérecquis de ce tutoriel, il est vivement conseillé de maßtriser les bases de HTML et CSS. Nous vous proposons le cours et le TD suivant : Cours d'introduction HTML/CSS. Diapos de présentation du cours d'introduction HTML/CSS. TD HTML-CSS : réaliser un petit site web ainsi que sa mise en forme. Pour aller plus loin et réaliser des animations CSS (facultatif pour le tuto pong).

Ce document a pour but de présenter une méthode rapide, ludique et efficace pour faire comprendre et manipuler les notions de base de la programmation web par le codage du jeu « Pong » en HTML/CSS/JavaScript.

Ce document a Ă©tĂ© utilisĂ© par plusieurs enseignants pour des Ă©lĂšves de seconde, 1Ăšre et terminale, ainsi que des Ă©tudiants en DSAA DSAA : DiplĂŽme SupĂ©rieur d’Arts AppliquĂ©s n’ayant aucune formation poussĂ©e en science. Ce document est donc destinĂ© aux dĂ©butants en programmation.

Suivre la construction pas Ă  pas d'un jeu comme Pong devrait permettre de comprendre et manipuler les notions de base de la programmation web HTML/CSS/JavaScript.

La structure HTML de la page et les propriétés CSS des élément seront manipulée à l'aide de JavaScript afin de créer le jeu qui sera en fait une page web dynamique et interactive.

On (re?)découvrira les notions programmation de base que sont les variables, tests, boucles, objets, etc.

Le tutoriel vous accompagnera pour Ă©crire le programme du jeu Pong. Il est dĂ©coupĂ© en Ă©tapes clĂ©s (crĂ©er une fenĂȘtre de jeu, tracer une balle, animer un objet, contrĂŽles au clavier, etc.) et il sera possible d'avancer Ă  votre rythme sans jamais ĂȘtre bloquĂ©. En effet, chaque partie sera organisĂ©e de la maniĂšre suivante :
  • Objectif : par exemple, afficher une balle
  • Explication thĂ©oriques : par exemple, comment positionner et donner une couleur Ă  une figure gĂ©omĂ©trique
  • Exercices : par exemple, tracer des cercles de couleurs diffĂ©rentes Ă  diffĂ©rentes positions de la fenĂȘtre
  • Correction ou indices

PremiĂšre prise en main

JavaScript est un langage de programmation utilisĂ© pour les pages web interactives. C'est un langage client, ce qui signifie qu'il est exĂ©cutĂ© par l'ordinateur de l'utilisateur, et non par le serveur du site hĂ©bergeant. Il peut toutefois ĂȘtre utilisĂ© comme langage de serveur (Node.js), ce qui n'est pas son utilisation initiale. Il existe depuis les dĂ©buts du web (1995) dĂ©montrant une longĂ©vitĂ© certaine. Langage interprĂ©tĂ© Ă  ses dĂ©buts (a priori plus lents que les langages compilĂ©s), il a Ă©voluĂ© pour devenir un langage compilĂ© Ă  la volĂ©e trĂšs rapide selon le moteur JavaScript. Il existe de nombreux Ă©diteurs et IDE (Interface De DĂ©veloppement) :
  • Notepad++
  • SublimeText
  • Eclipse
  • Atom
  • Vim
  • Brackets
  • etc.
Nous choisissons ici d'utiliser Notepad++ qui est à la fois générique, léger, gratuit et libre, mais qui n'est disponible que sous Windows. Il sera tout à fait possible d'utiliser l'éditeur de votre préférence. Si vous n'en connaissez aucun, commencez par suivre cette introduction à l'utilisation de Notepad++ : Introduction à l'utilisation de Notepad++ et à la programmation web
Dans cette partie, nous souhaitons créer :
  • un Ă©lĂ©ment HTML reprĂ©sentant le cadre de la zone du jeu avec une bordure
  • un Ă©lĂ©ment HTML fils de la zone de jeu, reprĂ©sentant une balle (avec des bords arrondis pour former un disque).
Le rendu devra correspondre Ă  l'image ci-dessous :
Afin de réalisé l'objectif précédent, il est important de bien comprendre comment sont positionnés les objets dans le plan, et la maniÚre de représenter les couleurs :

Comment sont représentées les couleurs numériquement ?

Positionnement dans une fenĂȘtre d'affichage.

En se basant sur les éléments de cours précédent positionnement CSS, on souhaite réaliser le premier objectif d'affichage de la balle dans un cadre.

Dans un dossier personnel, crĂ©er un sous-dossier intitulĂ© pong. Ouvrir un fichier vierge dans Notepad++. L'enregistrer sous le nom index.html dans le dossier pong (ne pas oublier l'extension .html). Ouvrir un deuxiĂšme fichier vierge dans Notepad++. L'enregistrer sous le nom pong.css. Visualiser la page index.html avec Firefox. Normalement, le rĂ©sultat est une page blanche. Dans le fichier index.html, placer le code minimal suivant : <!DOCTYPE html> <html lang="fr"> <head> <title>Pong</title> <link rel="stylesheet" href="pong.css"> </head> <body> Hello !!!! </body> </html> Enregistrez dans Notepad++, puis rafraĂźchissez la page firefox avec ou F5. Normalement, la page contient maintenant le texte "Hello !!!!" et un titre. Dans le code minimal, <link rel="stylesheet" href="pong.css"> permet de lier les deux fichiers html et css entre eux. En respectant les valeurs donnĂ©es dans les objectifs fixĂ©s (largeur, hauteur, Ă©paisseur, couleurs, etc.) : Dans le fichier index.html, crĂ©er la zone de jeu comme une div d'id zone-jeu. Dans le fichier pong.css, donner les valeurs souhaitĂ©es aux propriĂ©tĂ©s de l'Ă©lĂ©ment #zone-jeu. Dans le fichier index.html, crĂ©er la balle comme une div de classe ball Dans le fichier pong.css, donner les valeurs souhaitĂ©es aux propriĂ©tĂ©s de l'Ă©lĂ©ment .ball. La zone de jeu est identifiĂ©e par un id car elle est unique. La balle est caractĂ©risĂ©e par une classe, car elle pourrait ne pas ĂȘtre unique en cas de "jeu multi-balle".

Indice 1

S'inspirer des exercices sur le positionnement en CSS (copier-coller des parties).

Indice balle ronde 1

la propriété border-radius permet de préciser le rayon des coins arrondis.

Indice balle ronde 2

.ball{border-radius:50%;}
Changer la couleur du fond. Changer la taille et la forme de la balle. Changer la taille de la zone du jeu. Faire sortir la balle de la zone de jeu. Réaliser la figure suivante dans un nouveau fichier nommé cible.py:

Indice 1

Tracer 7 disques (un rouge, un blanc), de mĂȘme centre.

Indice 2

Les rayons sont des multiples de 10 pixels.

Indice 3

Commencer par dessiner le plus petit est une mauvaise idée.
La balle possÚde des attributs naturels (position, vitesse, couleur, etc. ), nous avons besoin pour les représenter de maniÚre informatique d'introduire les notions de variables et de types. On considÚre donc qu'à l'instant $t$, la balle est à la position $(x,y)$ dans un repÚre orthogonal $(O;I;J)$. A la frame suivante, à l'instant $t+dt$, sa nouvelle position est $(x+dx;y+dy)$. La balle est caractérisée par :
  • Sa position $(x,y)$
  • Son dĂ©placement $(dx,dy)$
  • Sa couleur $(r,g,b)$
  • Sa forme, qu'on considĂšrera ici comme circulaire.
La balle est également caractérisée par des actions : La balle réalisera les actions suivantes :
  • Afficher : Cela paraĂźt trivial, mais il est tout d’abord nĂ©cessaire de dessiner la balle pour qu’elle apparaisse sur la fenĂȘtre d’affichage. Il faut alors un cercle de rayon $r$, Ă  la position $(x,y)$, rempli avec la couleur $c$.
  • Avancer ou bouger : Faire avancer la balle de $dx$ suivant l’axe $x$ et de $dy$ suivant l’axe $y$, entre deux frames consĂ©cutives.
  • Rebondir ou Test de collision : Faire rebondir la balle sur les bords de la fenĂȘtre d’affichage. Par la suite, nous ferons Ă©voluer cette action en permettant la collision avec une raquette. Nous pourrons aussi rajouter du son Ă  chaque collision.
On peut aussi dĂ©finir un vecteur position $\vec{p} = \left(\begin{array}{c} x \\y \end{array}\right)$ ainsi qu’un vecteur dĂ©placement $\vec{d} = \left(\begin{array}{c} dx \\dy \end{array}\right)$. On considĂšre dans un premier temps deux paramĂštres au lieu d’un vecteur. Nous dĂ©finissons volontairement les paramĂštres de la balle comme « attributs » de la balle en prĂ©vision de la partie concernant la Programmation OrientĂ©e Objet, dans laquelle nous allons dĂ©finir les attributs de la classe « balle ». L’assimilation et la comprĂ©hension du concept d’attribut est ainsi facilitĂ©. Attention, dans les reprĂ©sentations d'images numĂ©riques et les logiciels de traitement d'image, l'axe des ordonnĂ©es est orientĂ© vers le bas.
L’ensemble des attributs de la balle $\{c, r, x,y, dx, dy\}$ est susceptible d’évoluer au fur et Ă  mesure de l’animation et de la vie de la balle. Il faut donc que le programme puisse manipuler et faire varier chacun de ces paramĂštres au fur et Ă  mesure de son exĂ©cution. Pour effectuer cette manipulation, en programmation, on utilise des variables. Il s’agit d’un espace mĂ©moire dans l’ordinateur attribuĂ© Ă  chacun des attributs de la balle. On peut assimiler cet espace Ă  une boite dans laquelle on place la valeur de la variable : La boite en question porte un nom pour la repĂ©rer de maniĂšre unique en mĂ©moire (ici : $x$) et prend une valeur (ici $5$). De maniĂšre analogue, en programmation, chaque variable Ă  un type dont voici une liste des principaux :
  • int : nombre entier
  • float : nombre flottant (Ă  virgule)
  • string : chaĂźne de caractĂšres
  • bool : boolĂ©en - valeur de vĂ©ritĂ© vrai ou faux
En physique, chaque grandeur a intrinsÚquement une unité. Par exemple :
  • La masse $m$ est en $kg$
  • La vitesse $v$ est en $m.s^{-1}$
  • Etc.
En mathématique, il existe différents ensemble de nombres. Par exemple :
  • Entiers naturels $\mathbb{N}$ : $0,1,2,3,...$
  • Nombres rationnels $\mathbb{Q}$ : $\frac{1}{3},0.5,...$
  • Les rĂ©els $\mathbb{R}$ : $\pi, e, \sqrt{2}$
  • Etc.
En informatique, un langage de programmation est dit fortement typĂ© lorsqu'il est nĂ©cessaire de dĂ©clarer systĂ©matiquement le type de chaque variable. Par opposition, un langage peut ĂȘtre faiblement typĂ© comme Python dans lequel les types des variables sont gĂ©rĂ©s automatiquement. Il est possible de vĂ©rifier le type d'une variable v en tapant type(v). VĂ©rifiez dans la console Python les types de :
  • 42
  • "salut"
  • 1.5
  • math.pi
  • True
  • "True"
Selon les types utilisés, les variables occupent des espaces de mémoire différents. Pour résumer, une variable est caractérisée par :
  • Un nom
  • Une valeur
  • Un type
Les variables caractérisant notre balles seront celles-ci :
Attributs de la balle Nom de la variable Type de la variable
Couleur c Liste de 3 entiers int
Rayon r int
Position (abscisse) x int
Position (ordonnée) y int
Déplacement (abscisse) dx int
Déplacement (ordonnée) dy int
Forme cercle (pour l'instant cette variable ne changera pas) ---
Ces variables sont dĂ©clarĂ©es en dĂ©but de programme, et utilisĂ©es par la suite dans toute le programme. C'est ce qu'on qualifie de variable globale.Les variables globales sont gĂ©nĂ©ralement Ă  Ă©viter dans des projets plus complexes. D'autres solutions sont prĂ©fĂ©rables, notamment les attributs d'une classe en programmation orientĂ©e objet. Ajoutons nos variables au programme prĂ©cĂ©dent : Le code est le suivant : #importation de la librairie pygame import pygame,sys from pygame.draw import * from pygame.display import * # variables globales #############################################" size = width, height = 500, 500 # taille de la fenĂȘtre d'affichage #attributs de la balle [dx,dy] = [2, 1]#vecteur de dĂ©placement entre deux frames consĂ©cutives couleurFond = [255, 0, 0]#rouge couleurBalle= [0,0,255]#bleu [x,y]=[100,100] # position initiale de la balle r=20 #rayon de la balle #lancement des fonctionnalitĂ©s de la librairie pygame pygame.init() #affichage d'une fenĂȘtre de dessin de largeur 500 pixels et de hauteur 500 pixels screen = set_mode(size) #remplissage du fond par la couleur dĂ©finie screen.fill(couleurFond) # dessin d'un cercle : # 0 : dernier paramĂštre - Ă©paisseur du contour (0 pour aucun contour) circle(screen, couleurBalle , [x,y], r, 0) # voir documentation : https://www.pygame.org/docs/ref/draw.html #activer le rendu graphique (sans lequel rien n'est affichĂ©) flip() pygame.time.delay(2000)#attend deux secondes pygame.display.quit()#ferme la fenĂȘtre sys.exit()#arrĂȘte le programme code source : pong0.3.py
L'objectif est maintenant de faire avancer la balle. Il va donc falloir simuler le mouvement par la sucession rapide de plusieurs images Ă  la maniĂšre d'un film. Une frĂ©quence de rafraĂźchissement de 30 images par seconde donne un rendu suffisamment fluide. Actuellement, l'image est tracĂ©e une seule fois. Il va falloir utiliser une boucle infinie modifiant le contenu de la fenĂȘtre d'affichage 30 fois par seconde. CelĂ  signifie que chaque itĂ©ration de la boucle doit durer $\frac{1}{30}$-Ăšme de seconde. La boucle While (signifiant "Tant que") permet de rĂ©pĂ©ter des instructions tant qu'une certaine condition est vĂ©rifiĂ©e. Tant que je n'ai pas gravi la montagne, je grimpe. Attention, si la condition n'est pas remplie, la boucle peut ĂȘtre infinie Ce qui formellement correspond Ă  ce schĂ©ma bloc : En langage Python, celĂ  s'Ă©crira : while condition: instruction_1 instruction_2 .... Dans le jeu, la boucle d'affichage ne doit jamais s'arrĂȘter... sauf quand on ferme la fenĂȘtre, ce qui sera gĂ©rĂ© plus tard. Nous allons utiliser une boucle infinie : Une boucle est infinie si la condition est toujours vĂ©rifiĂ©e. Autrement dit : "tant que la condition est vraie, ça boucle !!". Ce qui peut s'Ă©crire : while True: Instructions rĂ©pĂ©tĂ©es sans fin Pour commencer, nous souhaitons mettre la balle en mouvement comme ceci : Pour donner l'illusion du mouvement, nous devons ajouter une boucle infinie qui contient les instructions pour :
  1. Afficher la balle
  2. Déplacer la balle
  3. Attendre 15 ms ($\simeq 60$ fpsfps = "frames per second" ou "images par seconde" dans la langue de Jul)
  4. RafraĂźchir le contenu de la fenĂȘtre
  5. Test d'arrĂȘt pour sortir de la boucle et fermer Pygame
Entre chaque frame la balle doit se dĂ©placer de dx suivant l’axe x et dy suivant l’axe y. Il faut donc rajouter dans la boucle infinie les instructions suivantes : x ← x+dx y ← y+dy Ce qui donne le code suivant : #importation de la librairie pygame import pygame,sys from pygame.draw import * from pygame.display import * # variables globales ##########################################################" size = width, height = 500, 500 # taille de la fenĂȘtre d'affichage #attributs de la balle [dx,dy] = [2, 1]#vecteur de dĂ©placement entre deux frames consĂ©cutives couleurFond = [255, 0, 0]#rouge couleurBalle= [0,0,255]#bleu [x,y]=[100,100] # position initiale de la balle r=20 #rayon de la balle #lancement des fonctionnalitĂ©s de la librairie pygame pygame.init() #affichage d'une fenĂȘtre de dessin de largeur 500 pixels et de hauteur 500 pixels screen = set_mode(size) #remplissage du fond par la couleur blanche screen.fill(couleurFond) while True: #afficher la balle : circle(screen, couleurBalle , [x,y], r, 0)# dessin d'un cercle : #dĂ©placement de la balle : x=x+dx y=y+dy flip()#activer le rendu graphique pygame.time.delay(15)#une image toute les 15 ms #test d'arrĂȘt du jeu for event in pygame.event.get(): if event.type == pygame.QUIT:#si clique sur la croix quitter pygame.display.quit()#ferme la fenĂȘtre sys.exit()#arrĂȘte le programme code source : pong1.0.py

Normalement, le résultat est le suivant :

Nous remarquons que la balle laisse la trace de toutes les positions successive au cours du mouvement. Pour effacer les traces, il faut redessiner la couleur du fond Ă  chaque dĂ©but de boucle avant d'afficher la balle. Ce qui donne le code suivant : #importation de la librairie pygame import pygame,sys from pygame.draw import * from pygame.display import * # variables globales ##########################################################" size = width, height = 500, 500 # taille de la fenĂȘtre d'affichage #attributs de la balle [dx,dy] = [2, 1]#vecteur de dĂ©placement entre deux frames consĂ©cutives couleurFond = [255, 0, 0]#rouge couleurBalle= [0,0,255]#bleu [x,y]=[100,100] # position initiale de la balle r=20 #rayon de la balle #lancement des fonctionnalitĂ©s de la librairie pygame pygame.init() #affichage d'une fenĂȘtre de dessin de largeur 500 pixels et de hauteur 500 pixels screen = set_mode(size) while True: #remplissage du fond par la couleur blanche screen.fill(couleurFond) #afficher la balle : circle(screen, couleurBalle , [x,y], r, 0)# dessin d'un cercle : #dĂ©placement de la balle : x=x+dx y=y+dy flip()#activer le rendu graphique pygame.time.delay(15)#une image toute les 15 ms #test d'arrĂȘt du jeu for event in pygame.event.get(): if event.type == pygame.QUIT:#si clique sur la croix quitter pygame.display.quit()#ferme la fenĂȘtre sys.exit()#arrĂȘte le programme code source : pong1.1.py Il existe des opĂ©rateurs d’assignation qui permettent de simplifier l’écriture x = x+dx et y=y+dy. Ils se rĂ©sument dans le tableau suivant :
Attribution Ă  $x$ d'une valeur $a$ Ajouter $a$ Ă  une variable $x$ Retirer $a$ Ă  une variable $x$ Multiplier une variable $x$ par $a$ Diviser une variable $x$ par $a$
x=a x+=a x-=a x*=a x/=a
La partie « faire avancer la balle » du code prĂ©cĂ©dent peut se remplacer par : #dĂ©placement de la balle : x+=dx y+=dy La balle ne rebondit pas encore sur les bords. C’est l’objet de la partie suivante

On souhaite simuler le rebond sur bord droit comme ceci :

Convention de déplacement suivant $x$

D’aprùs l’orientation des axes (voir partie III-1) :
  • si la balle se dĂ©place de gauche Ă  droite, alors dx est positif
  • si la balle se dĂ©place de droite Ă  gauche, alors dx est nĂ©gatif

Condition de rebond

L'algorithme est le suivant : si (la balle touche le bord) alors le sens de dĂ©placement change de signe (sens opposĂ©) fin si MathĂ©matiquement, le changement de signe de dx revient Ă  multiplier cette valeur par -1. On Ă©crit : dx ← dx * (-1) En python, on peut l'Ă©crire : dx = dx * (-1) ou encore : dx *= -1 ou plus simplement : dx = -dx Il reste Ă  trouver Ă  quel moment la balle touche le bord. En rĂ©alitĂ©, le bord de la balle ne pourra quasiment jamais ĂȘtre rigoureusement tangent au bord vertical droit de la fenĂȘtre d’affichage. En effet, comme le dĂ©placement dx est de quelques pixels :
  • Ă  la frame d’avant la collision (instant $t_{n-1}$), le bord droit de la balle (point $M_{n-1}$) se situe Ă  une distance $a$ du bord de la fenĂȘtre d’affichage, telle que $0 \leq a \lt dx$
  • et Ă  l’instant d’aprĂšs la collision(instant $t_n$), le bord droit de la balle (point $M_n$) se situe Ă  une distance $b$ du bord de la fenĂȘtre d’affichage, telle que $0 \leq b \lt dx$.
Ce qui est rĂ©sumĂ© par l'image suivante : Dans la figure suivante, on remarque qu’à l’instant $t_n$, lors de la collision, le point $M_n$ d’abscisses $x+r$ dĂ©passe le bord droit de la fenĂȘtre d’affichage reprĂ©sentĂ© par la droite d’équation $x=width$.

On considÚre que la balle entre en collision avec le bord lorsque la condition suivante est vérifiée : $$(x+r >width)$$

Algorithme de la collision sur le bord vertical droit de la fenĂȘtre d’affichage

L’algorithme de collision sur le bord droit est donc le suivant : si la condition (x+r >width) est vraie alors dx ← -dx fin si On modifie la boucle infinie pour introduire la condition de rebond Ă  droite : while True: #remplissage du fond par la couleur blanche screen.fill(couleurFond) #afficher la balle : circle(screen, couleurBalle , [x,y], r, 0)# dessin d'un cercle : #dĂ©placement de la balle : x=x+dx y=y+dy #test de collision bords droit if x+r > width: dx=-dx flip()#activer le rendu graphique pygame.time.delay(15)#une image toute les 15 ms #test d'arrĂȘt du jeu for event in pygame.event.get(): if event.type == pygame.QUIT:#si clique sur la croix quitter pygame.display.quit()#ferme la fenĂȘtre sys.exit()#arrĂȘte le programme code source : pong1.2.py Dans le test « if », la condition $(x+r >width)$ est Ă©valuĂ©e et renvoie un boolĂ©en qui peut prendre la valeur « Vrai » ou « Faux ». Si la condition Ă©valuĂ©e renvoie « Vrai », alors un ensemble d’instructions est effectuĂ©. Ici, une seule instruction est rĂ©alisĂ©e : dx = -dx
On souhaite ajouter le rebond sur le bord gauche : En s'inspirant de la partie précédente, détecter et réaliser le rebond sur le bord vertical gauche.

Condition de rebond

Comme pour la collision sur le bord droit :
  • Ă  la frame d’avant la collision (instant $t_{n-1}$), le bord gauche de la balle (point $N_{n-1}$) se situe Ă  une distance $a$ du bord de la fenĂȘtre d’affichage, telle que $0 \leq a \lt dx$,
  • et Ă  l’instant d’aprĂšs la collision (instant $t_n$), le bord gauche de la balle (point $N_n$) se situe Ă  une distance $b$ du bord de la fenĂȘtre d’affichage, telle que $0 \leq b \lt dx$.
Dans la figure suivante, on remarque qu’à l’instant $t_n$, lors de la collision, le point $N_n$ d’abscisses $x-r$ dĂ©passe le bord droit de la fenĂȘtre d’affichage reprĂ©sentĂ© par la droite d’équation $x=width$.

On considÚre que la balle entre en collision avec le bord lorsque la condition suivante est vérifiée : $$(x-r \lt 0)$$

Algorithme de la collision sur le bord vertical droit de la fenĂȘtre d’affichage

L’algorithme de collision sur le bord droit est donc le suivant : si la condition (x-r < 0) est vraie alors dx ← -dx fin si On modifie la boucle infinie pour introduire la condition de rebond Ă  gauche : while True: #remplissage du fond par la couleur blanche screen.fill(couleurFond) #afficher la balle : circle(screen, couleurBalle , [x,y], r, 0)# dessin d'un cercle : #dĂ©placement de la balle : x=x+dx y=y+dy #test de collision bord droit if x+r > width: dx=-d #test de collision bord gauche if x-r < 0: dx=-dx flip()#activer le rendu graphique pygame.time.delay(15)#une image toute les 15 ms #test d'arrĂȘt du jeu for event in pygame.event.get(): if event.type == pygame.QUIT:#si clique sur la croix quitter pygame.display.quit()#ferme la fenĂȘtre sys.exit()#arrĂȘte le programme

code source : pong1.3.py

Si l'une des condition x+r > width OU x-r < 0 est remplie, elle rĂ©alisera la mĂȘme instruction dx = -dx. On peut regrouper ces deux conditions en un seul test : si (x+r > width) OU (x-r < 0) alors dx ← -dx fin si Ce qui peut ĂȘtre traduit de la maniĂšre suivante en python : while True: #remplissage du fond par la couleur blanche screen.fill(couleurFond) #afficher la balle : circle(screen, couleurBalle , [x,y], r, 0)# dessin d'un cercle : #dĂ©placement de la balle : x=x+dx y=y+dy #test de collision bords droite et gauche if (x+r > width) or (x-r < 0): dx=-dx flip()#activer le rendu graphique pygame.time.delay(15)#une image toute les 15 ms #test d'arrĂȘt du jeu for event in pygame.event.get(): if event.type == pygame.QUIT:#si clique sur la croix quitter pygame.display.quit()#ferme la fenĂȘtre sys.exit()#arrĂȘte le programme code source : pong1.4.py
On souhaite ajouter les rebonds sur les bords du haut et du bas : En s'inspirant des deux parties prĂ©cĂ©dentes, proposer une modification du code afin de rĂ©aliser les rebonds sur les bords horizontaux. Tout le raisonnement effectuĂ© pour la collision sur les bords verticaux se transpose intĂ©gralement par analogie sur les bords horizontaux. Dans les deux lignes de code correspondant Ă  l’action « Test de collision suivant x », il suffit d’effectuer les changements de variable suivants : $$ \begin{array}{ccc} \text{Axe } x & & \text{Axe }y\\ \hline x & \leftrightarrow & y \\ dx & \leftrightarrow & dy \\ width & \leftrightarrow & height \end{array} $$ Le code Python est le suivant : while True: #remplissage du fond par la couleur blanche screen.fill(couleurFond) #afficher la balle : circle(screen, couleurBalle , [x,y], r, 0)# dessin d'un cercle : #dĂ©placement de la balle : x=x+dx y=y+dy #test de collision bords droite et gauche if (x+r > width) or (x-r < 0): dx=-dx #test de collision bords haut et bas if (y+r > height) or (y-r < 0): dy=-dy flip()#activer le rendu graphique pygame.time.delay(15)#une image toute les 15 ms #test d'arrĂȘt du jeu for event in pygame.event.get(): if event.type == pygame.QUIT:#si clique sur la croix quitter pygame.display.quit()#ferme la fenĂȘtre sys.exit()#arrĂȘte le programme code source : pong1.5.py Lors des diffĂ©rents tests conditionnels, nous avons introduits un certain nombre d’opĂ©rateurs de comparaison (relationnels) qui peuvent se rĂ©sumer dans le tableau suivant :
supérieur inférieur supérieur ou égal inférieur ou égal égalité
> < >= <= ==
Nous avons introduit aussi un certain nombre d’opĂ©rateurs arithmĂ©tique :
addition soustraction multiplication division modulo (reste de la division euclidienne)
+ - * / %
Enfin nous avons introduits des opĂ©rateurs d’assignation :
Attribution Ă  $x$ d'une valeur $a$ Ajouter $a$ Ă  une variable $x$ Retirer $a$ Ă  une variable $x$ Multiplier une variable $x$ par $a$ Diviser une variable $x$ par $a$
x=a x+=a x-=a x*=a x/=a
Proposer une modification du code précédent pour que :
  • la balle ne rebondisse plus
  • mais qu'elle soit "tĂ©lĂ©portĂ©e" sur le bord opposĂ© (comme pour pacman)

Indice 1

Effacer la partie sur les rebonds

Indice 2

Utiliser l'opérateur modulo %

Indice 3

x "modulo" width
y "modulo" height
L'animation voulue est celle-ci : Le code Python est le suivant : while True: #remplissage du fond par la couleur blanche screen.fill(couleurFond) #afficher la balle : circle(screen, couleurBalle , [x,y], r, 0)# dessin d'un cercle : #dĂ©placement de la balle : x=(x+dx)%width y=(y+dy)%height flip()#activer le rendu graphique pygame.time.delay(15)#une image toute les 15 ms #test d'arrĂȘt du jeu for event in pygame.event.get(): if event.type == pygame.QUIT:#si clique sur la croix quitter pygame.display.quit()#ferme la fenĂȘtre sys.exit()#arrĂȘte le programme code source : pong-teleportation.py

Supposons qu’on souhaite maintenant faire Ă©voluer plusieurs balles dans la fenĂȘtre d’affichage. Chaque balle doit avoir un ensemble d’attributs et de variables associĂ©es qui lui est propre. Actuellement, chaque balle dispose de 6 attributs qui la caractĂ©risent de maniĂšre unique. Si on dĂ©cide de faire Ă©voluer 10 balles, cela revient Ă  manipuler 6*10 = 60 variables diffĂ©rentes. De mĂȘme, chaque balle doit avoir des actions propres (afficher, avancer, test de collision). Il faudrait donc dupliquer ces actions pour chaque balle.

Une mĂ©thode grossiĂšre consiste Ă  copier chaque partie du code rĂ©alisĂ© pour la premiĂšre balle et Ă  l’adapter pour chaque balle. Cela conduirait Ă  un code trĂšs long, rĂ©pĂ©titif et fastidieux Ă  lire.

Une des solutions pour remédier à ce problÚme est :
  • l’utilisation de « fonctions d’action » gĂ©nĂ©riques et rĂ©utilisables pour chaque balle
  • L'utilisation de listes de variables qui regroupent les attributs de toutes les balles en un seul objet.
  • l'utilisation d'une boucle « for » qui permet d’effectuer de maniĂšre itĂ©rative les mĂȘmes tĂąches rĂ©pĂ©titives pour chaque balle.
Nous introduisons dans un premier temps la notion de fonctionpour la balle unique créée dans la partie prĂ©cĂ©dente. Nous introduisons ensuite la notion de liste et de boucle for pour gĂ©rer les balles multiples. Lorsque la balle Ă©volue dans la fenĂȘtre d’affichage, pour chaque itĂ©ration de la boucle while, on peut rĂ©sumer notre programme par les actions Ă©lĂ©mentaires suivantes : Pour chaque itĂ©ration de la boucle : Afficher la balle Avancer Tester la collision Fin pour

Il suffit pour cela d’incorporer les diffĂ©rentes lignes de codes Ă©crites pour chaque actions dans la boucle while dans des fonctions indĂ©pendantes qui peuvent ĂȘtre appelĂ©es Ă  n’importe quel instant.

De maniĂšre gĂ©nĂ©rale, une fonction peut avoir des paramĂštres en entrĂ©e et renvoyer des paramĂštres en sortie. Dans le cas prĂ©sent, dans le cas d’une balle unique, on pourra dĂ©finir les fonctions suivantes :
  • afficher() : permet de dessiner la balle
  • avancer() : permet de faire avancer la balle
  • testCollision() : teste la collision sur les bords
A priori, aucune de ces méthodes ne prend de paramÚtre en entrée et ne renvoie de paramÚtre en sortie. Nous avons déjà utilisé quelques fonctions prédéfinies, issues de la libraire Pygame comme :
  • fill(color) : donne une couleur color au fond
  • circle(screen, couleurBalle , [x,y], r, 0) : dessine un cercle sur l'Ă©cran Ă  une position donnĂ©e, une couleur et un rayon.
  • etc.
Nous allons maintenant créer nos propres fonctions.
Les trois fonctions doivent ĂȘtre dĂ©clarĂ©es avant leur exĂ©cution (donc au dessus de la boucle while). Par exemple, pour la fonction afficher(), nous procĂ©dons de la maniĂšre suivante :
  • On dĂ©finit la mĂ©thode afficher() avec le mot clĂ© def
  • On dĂ©place les lignes de codes correspondant Ă  la partie « affichage de la balle », Ă  l’intĂ©rieur des accolades d’encapsulation de la fonction afficher().
On procĂšde de la mĂȘme maniĂšre pour les deux autres comme ceci : Le code est le suivant : #importation de la librairie pygame import pygame,sys from pygame.draw import * from pygame.display import * # variables globales ##########################################################" size = width, height = 500, 500 # taille de la fenĂȘtre d'affichage #attributs de la balle [dx,dy] = [3,1]#vecteur de dĂ©placement entre deux frames consĂ©cutives couleurFond = [255, 0, 0,10]#rouge couleurBalle= [0,0,255]#bleu [x,y]=[100,100] # position initiale de la balle r=20 #rayon de la balle # Nos fonctions d'actions def afficher(): circle(screen, couleurBalle , [x,y], r, 0) def avancer(): x=x+dx y=y+dy def testCollision(): #bords verticaux if x+r > width or x-r < 0: dx=-dx #bords horizontaux if y+r > height or y-r < 0: dy=-dy #lancement des fonctionnalitĂ©s de la librairie pygame pygame.init() #affichage d'une fenĂȘtre de dessin de largeur 500 pixels et de hauteur 500 pixels screen = set_mode(size) while True: #remplissage du fond par la couleur blanche screen.fill(couleurFond) #afficher la balle : afficher() #dĂ©placement de la balle : avancer() #test de collision testCollision() flip()#activer le rendu graphique pygame.time.delay(15)#une image toute les 15 ms #test d'arrĂȘt du jeu for event in pygame.event.get(): if event.type == pygame.QUIT:#si clique sur la croix quitter pygame.display.quit()#ferme la fenĂȘtre sys.exit()#arrĂȘte le programme code source : pong0=1.6.1.py Si vous avez exĂ©cutĂ© le programme prĂ©cĂ©dent avec les trois nouvelles fonctions, vous avez rencontrĂ© l'erreur suivante :
UnboundLocalError: local variable 'x' referenced before assignment

C'est normal ! CelĂ  signifie que la variable x est inconnue dans la fonction afficher().

En effet, les variables utilisĂ©es dans chaque fonction ont par dĂ©faut une portĂ©e locale. CelĂ  signifie qu'elle doivent ĂȘtre dĂ©clarĂ©e et utilisĂ©e Ă  l'intĂ©rieur de la fonction. Elle n'existent pas en dehors de cette fonction.

Si une variable, dĂ©clarĂ©e a l'extĂ©rieur, doit ĂȘtre utilisĂ©e et modifiĂ©e Ă  l'intĂ©rieur de la fonction il est nĂ©cessaire de la dĂ©clarĂ©e comme variable globale en dĂ©but de fonction comme ceci :

global x,y,dx,dy

Il suffit d'ajouter une ligne au début de chaque fonction pour que le programme fonctionne : # Nos fonctions d'actions def afficher(): global x,y,couleurBalle,r circle(screen, couleurBalle , [x,y], r, 0) def avancer(): global x,y,dx,dy x=x+dx y=y+dy def testCollision(): global x,y,width,height,r,dx,dy #bords verticaux if x+r > width or x-r < 0: dx=-dx #bords horizontaux if y+r > height or y-r < 0: dy=-dy code source : pong0=1.6.2.py
CrĂ©er une fonction testEvenement() qui s'occupe de la dĂ©tection des Ă©vĂšnements clavier/souris et qui gĂšre l'arrĂȘt du jeu et la fermeture de la fenĂȘtre.

Indice 1

Il s'agit de la partie du code qui commence par : for event in pygame.event.get():

Indice 2

Déclarer une fonction testEvenement() et y copier le code précédent

Indice 3

Ne pas oublier d'appeler la fonction dans la boucle while
#importation de la librairie pygame import pygame,sys from pygame.draw import * from pygame.display import * # variables globales ##########################################################" size = width, height = 500, 500 # taille de la fenĂȘtre d'affichage #attributs de la balle [dx,dy] = [3,1]#vecteur de dĂ©placement entre deux frames consĂ©cutives couleurFond = [255, 0, 0,10]#rouge couleurBalle= [0,0,255]#bleu [x,y]=[100,100] # position initiale de la balle r=20 #rayon de la balle # Nos fonctions d'actions def afficher(): circle(screen, couleurBalle , [x,y], r, 0) def avancer(): x=x+dx y=y+dy def testCollision(): #bords verticaux if x+r > width or x-r < 0: dx=-dx #bords horizontaux if y+r > height or y-r < 0: dy=-dy def testEvenement(): for event in pygame.event.get(): if event.type == pygame.QUIT:#si clique sur la croix quitter pygame.display.quit()#ferme la fenĂȘtre sys.exit()#arrĂȘte le programme #lancement des fonctionnalitĂ©s de la librairie pygame pygame.init() #affichage d'une fenĂȘtre de dessin de largeur 500 pixels et de hauteur 500 pixels screen = set_mode(size) while True: #remplissage du fond par la couleur blanche screen.fill(couleurFond) #afficher la balle : afficher() #dĂ©placement de la balle : avancer() #test de collision testCollision() flip()#activer le rendu graphique pygame.time.delay(15)#une image toute les 15 ms #test d'arrĂȘt du jeu testEvenement() code source : pong0=1.6.3.py
Nous allons maintenant faire Ă©voluer le programme de sorte qu’il puisse gĂ©rer un nombre N de balles. Pour cela, il est nĂ©cessaire d’introduite la notion de listes. Nous allons tout d’abord crĂ©er, puis manipuler 3 balles dont la gestion sera effectuĂ©e par l’utilisation de listes. Nous crĂ©erons ensuite un grand nombre de balles et introduiront la boucle itĂ©rative « for » pour pouvoir les manipuler. Comme nous l’avons vu prĂ©cĂ©demment, chaque balle dispose de 6 attributs qui la caractĂ©risent de maniĂšre unique. Si on dĂ©cide de faire Ă©voluer N=10 balles, cela revient Ă  manipuler 6*10 = 60 variables diffĂ©rentes, ce qui est trĂšs lourd.

La solution est de dĂ©finir une liste de valeurs pour chaque attribut de la balle. Si nous manipulons N balles, chaque liste comportera N valeurs de mĂȘme type. Chaque liste est alors considĂ©rĂ© comme une variable unique qui permet de manipuler N valeurs.

Quel que soit le nombre N de balles, l’utilisation des listes permet alors de ne manipuler que 6 variables correspondant à chaque attribut d’une balle.

Pour découvrir les listes, nous allons utiliser la console de l'IDE :

Dans la console, crĂ©er une liste L de 3 valeurs (qui pourrait reprĂ©senter une couleur RVB) >>> L = [20,10,15] Reprenons l'exemple prĂ©cĂ©dent (L Ă©tant toujours en mĂ©moire dans la console) : Il est possible d'accĂ©der Ă  un Ă©lĂ©ment d'une liste en prĂ©cisant son indice entre crochets []. Taper la commande suivante : >>> L[0] Elle doit renvoyer 20 car le premier Ă©lĂ©ment de la liste est repĂ©rĂ© par l'indice 0 Il est possible de modifier un Ă©lĂ©ment d'une liste avec une simple affectation. Taper la commande suivante : >>> L[0] = "pong is the best game !!" Afficher la liste LElle vaut maintenant ['pong is the best game!!', 10, 15]. Les listes en Python peuvent ĂȘtre composĂ©es d'objets de types diffĂ©rents. Ici L contient une chaĂźne de caractĂšre et deux entiers.
Commande Commentaire
len(L) La fonction len renvoie la longueur de la liste L
L.append(val) ajouter une valeur val aprÚs le dernier élément de la liste
L.insert(i,val) ajouter une valeur val aprÚs le i-Úme élément de la liste
L+=L0 concaténer la liste L0 à la liste L
del(L[i]) retirer le i-Úme élément de la liste L
a=L.pop() retirer le dernier élément de la liste L et le stocke dans a .
L.remove(val) retirer la premiĂšre occurence d'un Ă©lĂ©ment ayant la mĂȘme valeur que val .
L.reverse() renverse l'ordre
L.sort() réordonne les éléments de la liste
val in L renvoie True si un élément de la liste vaut val , False sinon.
val not in L renvoie False si un élément de la liste vaut val , True sinon.
Pour ĂȘtre sĂ»r d'avoir bien compris, on peut s'entraĂźner : Dans la console, utiliser les commandes prĂ©cĂ©dentes pour : Afficher la longueur de L Ajouter la valeur 42 Ă  la fin de la liste Ajouter la valeur 3.141592 en 2Ăšme position de la liste (attention le "premier" est L[0]) Retirer le 3-Ăšme Ă©lĂ©ment de la liste >>> len(L) >>> L.append(42) >>> L.insert(1,3.141592) >>> del(L[2]) ou L.remove(3.141592)
On va initialiser (avec des valeurs quelconques) des listes représentant les différents attributs de la balle :
  • dx : listes des dĂ©placements horizontaux entre deux frames
  • dy : liste des dĂ©placement verticaux entre deux frames
  • x : liste des abscisses des positions
  • y : liste des ordonnĂ©es des positions
  • r : liste des rayons des balles
Pour commencer, on donne la mĂȘme couleur Ă  chaque balle

Initialisation des listes

On donne 3 valeurs quelconques pour chaque attribut : dx = [3,2,5] #vecteur de déplacement entre deux frames consécutives dy = [-1, 1,3] x = [100, 250, 50] y = [30, 400, 100] r = [20, 25, 15]

Modification des fonctions d'action

Il faut préciser à chaque fonction l'indice i de la balle sur laquelle elle s'applique. On ajoute un argument i en entrée de la fonction : def afficher(i): global x,y,couleurBalle,r circle(screen, couleurBalle , [x[i],y[i]], r[i], 0) def avancer(i): global x,y,dx,dy x[i]=x[i]+dx[i] y[i]=y[i]+dy[i] def testCollision(i): global x,y,width,height,r,dx,dy #bords verticaux if x[i]+r[i] > width or x[i]-r[i] < 0: dx[i]=-dx[i] #bords horizontaux if y[i]+r[i] > height or y[i]-r[i] < 0: dy[i]=-dy[i]

Appels des fonctions d'action dans la boucle infinie

while True: #remplissage du fond par la couleur blanche screen.fill(couleurFond) #afficher la balle : afficher(0) afficher(1) afficher(2) #dĂ©placement de la balle : avancer(0) avancer(1) avancer(2) #test de collision testCollision(0) testCollision(1) testCollision(2) flip()#activer le rendu graphique pygame.time.delay(15)#une image toute les 15 ms #test evenements, arrĂȘt de jeu : testEvenements()

Code final

Le code final est le suivant : #importation de la librairie pygame import pygame,sys from pygame.draw import * from pygame.display import * # variables globales ##########################################################" size = width, height = 500, 500 # taille de la fenĂȘtre d'affichage couleurFond = [255, 0, 0,10]#rouge couleurBalle= [0,0,255]#les balles ont la mĂȘme couleur #balle dx = [3,2,5] #vecteur de dĂ©placement entre deux frames consĂ©cutives dy = [-1, 1,3] x = [100, 250, 50] y = [30, 400, 100] r = [20, 25, 15] # Nos fonctions d'actions def afficher(i): global x,y,couleurBalle,r circle(screen, couleurBalle , [x[i],y[i]], r[i], 0) def avancer(i): global x,y,dx,dy x[i]=x[i]+dx[i] y[i]=y[i]+dy[i] def testCollision(i): global x,y,width,height,r,dx,dy #bords verticaux if x[i]+r[i] > width or x[i]-r[i] < 0: dx[i]=-dx[i] #bords horizontaux if y[i]+r[i] > height or y[i]-r[i] < 0: dy[i]=-dy[i] def testEvenements(): for event in pygame.event.get(): if event.type == pygame.QUIT:#si clique sur la croix quitter pygame.display.quit()#ferme la fenĂȘtre sys.exit()#arrĂȘte le programme #lancement des fonctionnalitĂ©s de la librairie pygame pygame.init() #affichage d'une fenĂȘtre de dessin de largeur 500 pixels et de hauteur 500 pixels screen = set_mode(size) while True: #remplissage du fond par la couleur blanche screen.fill(couleurFond) #afficher la balle : afficher(0) afficher(1) afficher(2) #dĂ©placement de la balle : avancer(0) avancer(1) avancer(2) #test de collision testCollision(0) testCollision(1) testCollision(2) flip()#activer le rendu graphique pygame.time.delay(15)#une image toute les 15 ms #test evenements, arrĂȘt de jeu : testEvenements()   code source : pong2.0.py Modifier le code prĂ©cĂ©dent pour donner une couleur diffĂ©rente Ă  chaque balle en utilisant une liste de couleurs.

Indice 1

Vous pouvez déclarer 3 variables couleurBalle1, couleurBalle2 et couleurBalle3

Indice 2

Regrouper les 3 variables de couleurs dans une liste couleurBalle (une liste contenant des listes !)

Indice 3

Dans la fonction afficher(i), utiliser la bonne couleur couleurBalle1[i]
#importation de la librairie pygame import pygame,sys from pygame.draw import * from pygame.display import * # variables globales ##########################################################" size = width, height = 500, 500 # taille de la fenĂȘtre d'affichage couleurFond = [255, 0, 0,10]#rouge #balle dx = [3,2,5] #vecteur de dĂ©placement entre deux frames consĂ©cutives dy = [-1, 1,3] x = [100, 250, 50] y = [30, 400, 100] r = [20, 25, 15] #tableau de couleur couleurBalle1= [0,0,255]#les balles ont la mĂȘme couleur couleurBalle2= [255,0,255]#les balles ont la mĂȘme couleur couleurBalle3= [255,255,255]#les balles ont la mĂȘme couleur couleurBalle = [couleurBalle1,couleurBalle2,couleurBalle3] # Nos fonctions d'actions def afficher(i): global x,y,couleurBalle,r circle(screen, couleurBalle[i] , [x[i],y[i]], r[i], 0) def avancer(i): global x,y,dx,dy x[i]=x[i]+dx[i] y[i]=y[i]+dy[i] def testCollision(i): global x,y,width,height,r,dx,dy #bords verticaux if x[i]+r[i] > width or x[i]-r[i] < 0: dx[i]=-dx[i] #bords horizontaux if y[i]+r[i] > height or y[i]-r[i] < 0: dy[i]=-dy[i] def testEvenements(): for event in pygame.event.get(): if event.type == pygame.QUIT:#si clique sur la croix quitter pygame.display.quit()#ferme la fenĂȘtre sys.exit()#arrĂȘte le programme #lancement des fonctionnalitĂ©s de la librairie pygame pygame.init() #affichage d'une fenĂȘtre de dessin de largeur 500 pixels et de hauteur 500 pixels screen = set_mode(size) while True: #remplissage du fond par la couleur blanche screen.fill(couleurFond) #afficher la balle : afficher(0) afficher(1) afficher(2) #dĂ©placement de la balle : avancer(0) avancer(1) avancer(2) #test de collision testCollision(0) testCollision(1) testCollision(2) flip()#activer le rendu graphique pygame.time.delay(15)#une image toute les 15 ms #test evenements, arrĂȘt de jeu : testEvenements() code source : pong2.1.py
Nous souhaitons pouvoir afficher un nombre quelconque de balles. On propose une méthode plus générale pour déclarer les listes qui s'adaptera beaucoup mieux à la gestion d'un grand nombre de balles.
  • On dĂ©clare une liste vide
  • On ajoute chaque Ă©lĂ©ment de la liste l'un aprĂšs l'autre avec la mĂ©thode append vue prĂ©cĂ©demment
Cela permettra de plus d'ajouter ou de retirer des balles pendant le jeu.
Appliquer la méthode générale pour modifier dans le code précédent la déclaration des listes dx, dy, x, y et r.

Indice 1

Affection d'une liste vide : dx=[]

Indice 2

Ajouter un élément à la liste : dx.append(valeur)

Indice 3

Ajouter un autre élément à la liste : dx.append(nouvelleValeur)
# déclaration des listes vides des attributs des balles dx = [] #vecteur de déplacement entre deux frames consécutives dy = [] x = [] y = [] r = [] #initialisation des listes dx.append(3) dx.append(2) dx.append(5) dy.append(-1) dy.append(1) dy.append(3) x.append(100) x.append(250) x.append(50) y.append(100) y.append(400) y.append(100) r.append(20) r.append(25) r.append(15) code source : pong2.2.py Cette méthode semble pour l'instant plus longue que la précédente, mais s'adaptera parfaitement à un nombre de balles plus important.
En prévision d'un nombre de balles important, on souhaite ne pas avoir à gérer les valeurs de tous les attributs à la main. Nous proposons de les générer aléatoirement. Nous proposons de faire appel à la librairie python randomrandom signifie aléatoire en anglais On va tirer au hasard des nombres entiers. Pour cela on n'aura besoin que de la fonction randint() de la librairie random. On l'importe de la maniÚre suivante : from random import randint Pour tirer un nombre au hasard entre valMin et valMax (compris), on utilise : randint(valMin, valMax) Appliquer cette méthode pour donner des valeurs aléatoires aux éléments des listes dx, dy, x, y, r ET couleurBalle

Indice 1

Définir des variables rMin, rMax, dxMin, dxMax, dyMin, dyMax permettant de borner les valeurs aléatoires.

Indice 2

Les balles peuvent se dĂ©placer vers la gauche... dxMin doit ĂȘtre nĂ©gatif.

Indice 3

dx.append(randint(dxMin,dxMax))

Indice 4

Attention à ne pas créer une balle qui sort du cadre : x.append(randint(rmax,width-rmax))

Indice 5

Les valeurs RVB des couleurs sont comprises entre 0 et 255
#importation de la librairie pygame import pygame,sys from pygame.draw import * from pygame.display import * from random import randint # variables globales ##########################################################" size = width, height = 500, 500 # taille de la fenĂȘtre d'affichage couleurFond = [255, 0, 0,10]#rouge couleurBalle1= [0,0,255]#les balles ont la mĂȘme couleur dxMin=-5 dxMax=5 dyMin=-5 dyMax=5 rmax = 40 rmin = 10 # dĂ©claration des listes vides des attributs des balles dx = [] #vecteur de dĂ©placement entre deux frames consĂ©cutives dy = [] x = [] y = [] r = [] #initialisation des listes dx.append(randint(dxMin,dxMax)) dx.append(randint(dxMin,dxMax)) dx.append(randint(dxMin,dxMax)) dy.append(randint(dyMin,dyMax)) dy.append(randint(dyMin,dyMax)) dy.append(randint(dyMin,dyMax)) x.append(randint(rmax,width-rmax)) x.append(randint(rmax,width-rmax)) x.append(randint(rmax,width-rmax)) y.append(randint(rmax,height-rmax)) y.append(randint(rmax,height-rmax)) y.append(randint(rmax,height-rmax)) r.append(randint(rmin,rmax)) r.append(randint(rmin,rmax)) r.append(randint(rmin,rmax)) #tableau de couleur (dĂ©gradĂ© de bleu) couleurBalle1= [0,0,randint(0,255)] couleurBalle2= [0,0,randint(0,255)] couleurBalle3= [0,0,randint(0,255)] couleurBalle = [couleurBalle1,couleurBalle2,couleurBalle3] # Nos fonctions d'actions def afficher(i): global x,y,couleurBalle,r circle(screen, couleurBalle[i] , [x[i],y[i]], r[i], 0) def avancer(i): global x,y,dx,dy x[i]=x[i]+dx[i] y[i]=y[i]+dy[i] def testCollision(i): global x,y,width,height,r,dx,dy #bords verticaux if x[i]+r[i] > width or x[i]-r[i] < 0: dx[i]=-dx[i] #bords horizontaux if y[i]+r[i] > height or y[i]-r[i] < 0: dy[i]=-dy[i] def testEvenements(): for event in pygame.event.get(): if event.type == pygame.QUIT:#si clique sur la croix quitter pygame.display.quit()#ferme la fenĂȘtre sys.exit()#arrĂȘte le programme #lancement des fonctionnalitĂ©s de la librairie pygame pygame.init() #affichage d'une fenĂȘtre de dessin de largeur 500 pixels et de hauteur 500 pixels screen = set_mode(size) while True: #remplissage du fond par la couleur blanche screen.fill(couleurFond) #afficher la balle : afficher(0) afficher(1) afficher(2) #dĂ©placement de la balle : avancer(0) avancer(1) avancer(2) #test de collision testCollision(0) testCollision(1) testCollision(2) flip()#activer le rendu graphique pygame.time.delay(15)#une image toute les 15 ms #test evenements, arrĂȘt de jeu : testEvenements() code source : pong2.3.py
La boucle itĂ©rative « for » permets l’exĂ©cution d’un bloc d’instructions un certain nombre de fois, en faisant gĂ©nĂ©ralement varier un indice entre une valeur initiale et une valeur finale avec un pas d’incrĂ©mentation. Lorsque le nombre N de balle est grand, il ne sera trĂšs fastidieux dĂ©clarer et d'initialiser "Ă  la main" chacun des 6 paramĂštres de chaque balle. En effet, supposons que nous crĂ©ons 30 balles, le nombre de paramĂštres Ă  initialiser est 30*6=180. La solution est d'utiliser une boucle itĂ©rative for qui permet l’exĂ©cution d’un bloc d’instructions un certain nombre de fois, en faisant gĂ©nĂ©ralement varier un indice entre une valeur initiale et une valeur finale avec un pas d’incrĂ©mentation for i in range(0,5): print("l'indice vaut : ", i ) Ce code affichera : l'indice vaut : 0 l'indice vaut : 1 l'indice vaut : 2 l'indice vaut : 3 l'indice vaut : 4 L'indice i varie d'une valeur initiale i=0 Ă  une valeur finale i=4 et non 5 !!. Une petite prĂ©cision concernant range() Si on exĂ©cute dans la console list(range(0,5)), on obtient : [0, 1, 2, 3, 4] Cette commande crĂ©e une liste de 5 Ă©lĂ©ments de 0 Ă  4 avec un pas de 1. Tapez dans la console les commandes suivantes pour comprendre le fonctionnement de range. list(range(2,5)) list(range(0,100,10)) list(range(10,0,-1)) Quel est le rĂŽle du troisiĂšme argument ?
  • Le troisiĂšme argument reprĂ©sente le pas d'incrĂ©mentation de la liste
  • La derniĂšre valeur n'est pas atteinte
  • Le pas peut ĂȘtre nĂ©gatif
  • Le pas ne peut ĂȘtre qu'entier
On comprend donc que la boucle for peut itérer sur n'importe quelle liste : L=["Marseille","New York","Alger","Tokyo","Dakar"] for ville in L: print("J'adore la ville de ", ville ) Ce code affichera : J'adore la ville de Marseille J'adore la ville de New York J'adore la ville de Alger J'adore la ville de Tokyo J'adore la ville de Dakar
Il est maintenant possible d’appliquer la boucle « for » pour simplifier l’écriture des taches itĂ©ratives :
  • Pour l’initialisation des diffĂ©rents tableaux dans le setup() : d, x, y, dx, dy, c.
  • Pour l’appel aux diffĂ©rentes mĂ©thodes appliquĂ©es Ă  chaque balle : affiche(i), avancer(i) et testCollision(i).
Modifier le code du pong prĂ©cĂ©dent pour gĂ©rer les instruction rĂ©pĂ©titives Ă©crites Ă  la main Ă  l'aide de boucles for. #importation de la librairie pygame import pygame,sys from pygame.draw import * from pygame.display import * from random import randint # variables globales ##########################################################" size = width, height = 500, 500 # taille de la fenĂȘtre d'affichage couleurFond = [255, 0, 0,10]#rouge couleurBalle1= [0,0,255]#les balles ont la mĂȘme couleur rmax = 40 rmin = 10 # dĂ©claration des listes vides des attributs des balles dx = [] #vecteur de dĂ©placement entre deux frames consĂ©cutives dy = [] x = [] y = [] r = [] couleurBalle = [] #initialisation des listes for i in range(0,3): dx.append(randint(-5,5)) dy.append(randint(-5,5)) x.append(randint(width-rmax,height-rmax)) y.append(randint(width-rmax,height-rmax)) r.append(randint(rmin,rmax)) #tableau de couleur (dĂ©gradĂ© de bleu) couleurBalle.append([0,0,randint(0,255)]) # Nos fonctions d'actions def afficher(i): global x,y,couleurBalle,r circle(screen, couleurBalle[i] , [x[i],y[i]], r[i], 0) def avancer(i): global x,y,dx,dy x[i]=x[i]+dx[i] y[i]=y[i]+dy[i] def testCollision(i): global x,y,width,height,r,dx,dy #bords verticaux if x[i]+r[i] > width or x[i]-r[i] < 0: dx[i]=-dx[i] #bords horizontaux if y[i]+r[i] > height or y[i]-r[i] < 0: dy[i]=-dy[i] def testEvenements(): for event in pygame.event.get(): if event.type == pygame.QUIT:#si clique sur la croix quitter pygame.display.quit()#ferme la fenĂȘtre sys.exit()#arrĂȘte le programme #lancement des fonctionnalitĂ©s de la librairie pygame pygame.init() #affichage d'une fenĂȘtre de dessin de largeur 500 pixels et de hauteur 500 pixels screen = set_mode(size) while True: #remplissage du fond par la couleur blanche screen.fill(couleurFond) for i in range(0,3): #afficher la balle : afficher(i) #dĂ©placement de la balle : avancer(i) #test de collision testCollision(i) flip()#activer le rendu graphique pygame.time.delay(15)#une image toute les 15 ms #test evenements, arrĂȘt de jeu : testEvenements() code source : pong2.4.py L'intĂ©rĂȘt des boucles for est que maintenant, la structure du programme pour afficher 1, 3, 10 ou 30 balles est la mĂȘme. Introduire une nouvelle variable globale N qui reprĂ©sente le nombre de balles. Modifier le code prĂ©cĂ©dent pour afficher N balles. Testez diffĂ©rentes valeurs. #importation de la librairie pygame import pygame,sys from pygame.draw import * from pygame.display import * from random import randint # variables globales ##########################################################" size = width, height = 500, 500 # taille de la fenĂȘtre d'affichage couleurFond = [255, 0, 0,10]#rouge couleurBalle1= [0,0,255]#les balles ont la mĂȘme couleur rmax = 40 rmin = 10 N = 10 #nb de balles # dĂ©claration des listes vides des attributs des balles dx = [] #vecteur de dĂ©placement entre deux frames consĂ©cutives dy = [] x = [] y = [] r = [] couleurBalle = [] #initialisation des listes for i in range(0,N): dx.append(randint(-5,5)) dy.append(randint(-5,5)) x.append(randint(width-rmax,height-rmax)) y.append(randint(width-rmax,height-rmax)) r.append(randint(rmin,rmax)) #tableau de couleur (dĂ©gradĂ© de bleu) couleurBalle.append([0,0,randint(0,255)]) # Nos fonctions d'actions def afficher(i): global x,y,couleurBalle,r circle(screen, couleurBalle[i] , [x[i],y[i]], r[i], 0) def avancer(i): global x,y,dx,dy x[i]=x[i]+dx[i] y[i]=y[i]+dy[i] def testCollision(i): global x,y,width,height,r,dx,dy #bords verticaux if x[i]+r[i] > width or x[i]-r[i] < 0: dx[i]=-dx[i] #bords horizontaux if y[i]+r[i] > height or y[i]-r[i] < 0: dy[i]=-dy[i] def testEvenements(): for event in pygame.event.get(): if event.type == pygame.QUIT:#si clique sur la croix quitter pygame.display.quit()#ferme la fenĂȘtre sys.exit()#arrĂȘte le programme #lancement des fonctionnalitĂ©s de la librairie pygame pygame.init() #affichage d'une fenĂȘtre de dessin de largeur 500 pixels et de hauteur 500 pixels screen = set_mode(size) while True: #remplissage du fond par la couleur blanche screen.fill(couleurFond) for i in range(0,N): #afficher la balle : afficher(i) #dĂ©placement de la balle : avancer(i) #test de collision testCollision(i) flip()#activer le rendu graphique pygame.time.delay(15)#une image toute les 15 ms #test evenements, arrĂȘt de jeu : testEvenements() code source : pong2.5.py
La raquette est positionnée à gauche par convention. Son abscisse est donc fixe, et son ordonnée sera commandée par des interaction clavier. On ajoute donc plusieurs variables pour représenter la raquette :
  • rx = 20 : abscisse de la raquette
  • ry = height/2 : ordonnĂ©e de la raquette (positionnĂ©e au milieu initialement mais qui variera)
  • dry = 5 : dĂ©placement vertical de la raquette
  • rh = 100 : hauteur de la raquette
  • rw = 20 : largeur de la raquette
  • rcolor = [255, 255, 255] : couleur de la raquette (ici blanc)
Pour reprĂ©senter graphique la raquette, il suffit de dessiner un rectangle. On utilise la methode pygame.draw.rect() qui s'utilise de la maniĂšre suivante : rect(screen, rcolor, [rx, ry, rw, rh]) Afficher une raquette blanche dans la fenĂȘtre du jeu avec les caractĂ©ristiques prĂ©cĂ©dentes On ajoute les variables et une fonction afficher_raquette() : #importation de la librairie pygame import pygame,sys from pygame.draw import * from pygame.display import * from random import randint # variables globales ##########################################################" size = width, height = 500, 500 # taille de la fenĂȘtre d'affichage couleurFond = [255, 0, 0,10]#rouge couleurBalle1= [0,0,255]#les balles ont la mĂȘme couleur rmax = 40 rmin = 10 N = 10 #nb de balles # dĂ©claration des listes vides des attributs des balles dx = [] #vecteur de dĂ©placement entre deux frames consĂ©cutives dy = [] x = [] y = [] r = [] couleurBalle = [] #dĂ©claration des attributs de la raquette rx=20 ry=height/2 dry=5 rh=100 rw=20 rcolor=[255,255,255] #initialisation des listes for i in range(0,N): dx.append(randint(-5,5)) dy.append(randint(-5,5)) x.append(randint(width-rmax,height-rmax)) y.append(randint(width-rmax,height-rmax)) r.append(randint(rmin,rmax)) #tableau de couleur (dĂ©gradĂ© de bleu) couleurBalle.append([0,0,randint(0,255)]) # Nos fonctions d'actions def afficher(i): global x,y,couleurBalle,r circle(screen, couleurBalle[i] , [x[i],y[i]], r[i], 0) def avancer(i): global x,y,dx,dy x[i]=x[i]+dx[i] y[i]=y[i]+dy[i] def testCollision(i): global x,y,width,height,r,dx,dy #bords verticaux if x[i]+r[i] > width or x[i]-r[i] < 0: dx[i]=-dx[i] #bords horizontaux if y[i]+r[i] > height or y[i]-r[i] < 0: dy[i]=-dy[i] def testEvenements(): for event in pygame.event.get(): if event.type == pygame.QUIT:#si clique sur la croix quitter pygame.display.quit()#ferme la fenĂȘtre sys.exit()#arrĂȘte le programme #fonctions de la raquette def afficher_raquette(): rect(screen, rcolor, [rx, ry, rw, rh]) #lancement des fonctionnalitĂ©s de la librairie pygame pygame.init() #affichage d'une fenĂȘtre de dessin de largeur 500 pixels et de hauteur 500 pixels screen = set_mode(size) while True: #remplissage du fond par la couleur blanche screen.fill(couleurFond) for i in range(0,N): #afficher la balle : afficher(i) #dĂ©placement de la balle : avancer(i) #test de collision testCollision(i) afficher_raquette() flip()#activer le rendu graphique pygame.time.delay(15)#une image toute les 15 ms #test evenements, arrĂȘt de jeu : testEvenements() code source : pong3.0.py
On a besoin d'interagir avec le clavier (flĂšche du haut et flĂšche du bas) pour commander la position de la raquette. On va importer les importer les attributs de pygame au dĂ©but du programme en ajoutant la ligne suivante en entĂȘte du programme : from pygame.locals import * Cela nous permettra de taper KEYDOWN ou QUIT ou K_UP, etc. au lieu de pygame.KEYDOWN ou pygame.QUIT ou pygame.K_UP, etc. L'appui sur une touche est considĂ©rĂ© par pygame comme un nouvel Ă©vĂšnement. Nous avons dĂ©jĂ  créé la fonction testEvenements() qui gĂšre l'Ă©vĂšnement "quitter la fenĂȘtre de jeu". Si l'Ă©vĂšnement vaut pygame.KEYDOWN, c'est que une touche (n'importe laquelle) a Ă©tĂ© appuyĂ©e. On modifie maintenant la fonction testEvenement() comme ceci : def testEvenements(): for event in pygame.event.get(): if event.type == QUIT:#si clique sur la croix quitter pygame.display.quit()#ferme la fenĂȘtre sys.exit()#arrĂȘte le programme if event.type == KEYDOWN: print("Une touche vient d'ĂȘtre pressĂ©e") Pour l'instant appuyer sur une touche ne produit aucun rĂ©sultat visible sur la raquette, et ne fait qu'afficher un message dans la console. La prochaine Ă©tape est de dĂ©tecter quelle touche a Ă©tĂ© pressĂ©e.
  • La mĂ©thode pygame.key.get_pressed() renvoie une liste reprĂ©sentant l'Ă©tat de chaque touche du clavier : 1 pour appuyĂ©e, 0 pour relĂąchĂ©e.
  • L'indice de la touche "flĂšche du haut" dans le tableau pygame.key.get_pressed() est 273, celui de "flĂšche du bas" est 274
  • Pour ne pas avoir Ă  retenir ces indices, pygame a dĂ©fini des constantes : K_UP vaut 273 et K_DOWN vaut 274.
  • Les noms de toutes les constantes associĂ©es Ă  chaque touche sont disponibles sur le site de pygame.
On donne la fonction bouger_raquette() suivante : def bouger_raquette(): global ry, dry if pygame.key.get_pressed()[K_UP]: #dĂ©placer vers le haut .... if pygame.key.get_pressed()[K_DOWN]: #dĂ©placer vers le bas .... ComplĂ©ter le code de la fonction bouge_raquette() afin de rĂ©aliser le dĂ©placement souhaitĂ©. Appeler cette fonction lorsqu'un Ă©vĂšnement KEYDOWN est dĂ©tectĂ© def testEvenements(): for event in pygame.event.get(): if event.type == pygame.QUIT:#si clique sur la croix quitter pygame.display.quit()#ferme la fenĂȘtre sys.exit()#arrĂȘte le programme if event.type == KEYDOWN: bouger_raquette() def bouger_raquette(): global ry, dry if pygame.key.get_pressed()[K_UP]: ry-=dry if pygame.key.get_pressed()[K_DOWN]: ry+=dry Vous avez certainement remarquĂ© qu'il faut appuyer plusieurs fois sur les touches bas et haut pour dĂ©placer le raquette. Maintenir une touche appuyĂ©e ne dĂ©clenche qu'un seul Ă©vĂšnement clavier. Pour obliger pygame Ă  vĂ©rifier les Ă©venements claviers toutes les 10ms (par exemple), il faut ajouter la ligne suivante juste aprĂšs avoir initialisĂ© pygame : #lancement des fonctionnalitĂ©s de la librairie pygame pygame.init() #vĂ©rifier les interactions clavier toutes les 10ms pygame.key.set_repeat(10, 10) On obtient donc le code entier suivant : #importation de la librairie pygame from pygame.locals import * import pygame,sys from pygame.draw import * from pygame.display import * from random import randint # variables globales ##########################################################" size = width, height = 500, 500 # taille de la fenĂȘtre d'affichage couleurFond = [255, 0, 0,10]#rouge couleurBalle1= [0,0,255]#les balles ont la mĂȘme couleur rmax = 40 rmin = 10 N = 10 #nb de balles # dĂ©claration des listes vides des attributs des balles dx = [] #vecteur de dĂ©placement entre deux frames consĂ©cutives dy = [] x = [] y = [] r = [] couleurBalle = [] #dĂ©claration des attributs de la raquette rx=20 ry=height/2 dry=2 rh=100 rw=20 rcolor=[255,255,255] #initialisation des listes for i in range(0,N): dx.append(randint(-5,5)) dy.append(randint(-5,5)) x.append(randint(width-rmax,height-rmax)) y.append(randint(width-rmax,height-rmax)) r.append(randint(rmin,rmax)) #tableau de couleur (dĂ©gradĂ© de bleu) couleurBalle.append([0,0,randint(0,255)]) # Nos fonctions d'actions def afficher(i): global x,y,couleurBalle,r circle(screen, couleurBalle[i] , [x[i],y[i]], r[i], 0) def avancer(i): global x,y,dx,dy x[i]=x[i]+dx[i] y[i]=y[i]+dy[i] def testCollision(i): global x,y,width,height,r,dx,dy #bords verticaux if x[i]+r[i] > width or x[i]-r[i] < 0: dx[i]=-dx[i] #bords horizontaux if y[i]+r[i] > height or y[i]-r[i] < 0: dy[i]=-dy[i] def testEvenements(): for event in pygame.event.get(): if event.type == QUIT:#si clique sur la croix quitter pygame.display.quit()#ferme la fenĂȘtre sys.exit()#arrĂȘte le programme if event.type == KEYDOWN: bouger_raquette() #fonctions de la raquette def afficher_raquette(): rect(screen, rcolor, [rx, ry, rw, rh]) def bouger_raquette(): global ry, dry if pygame.key.get_pressed()[K_UP]: ry-=dry if pygame.key.get_pressed()[K_DOWN]: ry+=dry #lancement des fonctionnalitĂ©s de la librairie pygame pygame.init() #vĂ©rifier les interactions clavier toutes les 10ms pygame.key.set_repeat(10, 10) #affichage d'une fenĂȘtre de dessin de largeur 500 pixels et de hauteur 500 pixels screen = set_mode(size) while True: #remplissage du fond par la couleur blanche screen.fill(couleurFond) for i in range(0,N): #afficher la balle : afficher(i) #dĂ©placement de la balle : avancer(i) #test de collision testCollision(i) afficher_raquette() flip()#activer le rendu graphique pygame.time.delay(15)#une image toute les 15 ms #test evenements, arrĂȘt de jeu : testEvenements() code source : pong3.1.py
Nous proposons ici de modifier la fonction testCollision(i) qui teste la collision de la ballei avec les bords. Il est nĂ©cessaire de faire un schĂ©ma pour bien comprendre la situation : Pour qu’il y ait collision entre la balle et la raquette, il faut que le point N de la iĂšme balle soit tangent ou traverse lĂ©gĂšrement le bord droit de la raquette. Les conditions suivantes doivent simultanĂ©ment ĂȘtre respectĂ©es :
  • Suivant x : l’abscisse du point N doit ĂȘtre infĂ©rieure Ă  celle du point A et B, soit, $$ x – r \lt rx + rw $$
  • Suivant y : l’ordonnĂ©e du point N doit ĂȘtre comprise entre l’ordonnĂ©e du point A et l’ordonnĂ©e du point B, soit, $$ ry \lt y \lt ry + rh . $$
Algorithmiquement, il faut donc que la condition $ry \lt y$ et que la condition $ y \lt ry + rh$ et que la condition $x – r \lt rx+rw$ soient vĂ©rifiĂ©es simultanĂ©ment. En programmation Python, le « et logique » s’écrit and. Pour la i-Ăšme balle, cette condition logique s'Ă©crit donc : (ry < y[i]) and (y[i] < (ry + rh)) and ((x[i] – r[i]) < (rx+rw)) Modifier la fonction testCollision pour que le bord droit de la raquette se comporte comporte comme le bord droit de l'Ă©cran et fasse rebondir la balle. def testCollision(i): global x,y,width,height,r,dx,dy,ry,rh,rw #bords verticaux if x[i]+r[i] > width or x[i]-r[i] < 0: dx[i]=-dx[i] #bords horizontaux if y[i]+r[i] > height or y[i]-r[i] < 0: dy[i]=-dy[i] #rebond raquette : if (ry < y[i]) and (y[i] < (ry + rh)) and ((x[i] - r[i]) < (rx + rw)): dx[i]=-dx[i] Ce qui produit le programme final suivant : #importation de la librairie pygame from pygame.locals import * import pygame,sys from pygame.draw import * from pygame.display import * from random import randint # variables globales ##########################################################" size = width, height = 500, 500 # taille de la fenĂȘtre d'affichage couleurFond = [255, 0, 0,10]#rouge couleurBalle1= [0,0,255]#les balles ont la mĂȘme couleur rmax = 40 rmin = 10 N = 10 #nb de balles # dĂ©claration des listes vides des attributs des balles dx = [] #vecteur de dĂ©placement entre deux frames consĂ©cutives dy = [] x = [] y = [] r = [] couleurBalle = [] #dĂ©claration des attributs de la raquette rx=20 ry=height/2 dry=2 rh=100 rw=20 rcolor=[255,255,255] #initialisation des listes for i in range(0,N): dx.append(randint(-5,5)) dy.append(randint(-5,5)) x.append(randint(width-rmax,height-rmax)) y.append(randint(width-rmax,height-rmax)) r.append(randint(rmin,rmax)) #tableau de couleur (dĂ©gradĂ© de bleu) couleurBalle.append([0,0,randint(0,255)]) # Nos fonctions d'actions def afficher(i): global x,y,couleurBalle,r circle(screen, couleurBalle[i] , [x[i],y[i]], r[i], 0) def avancer(i): global x,y,dx,dy x[i]=x[i]+dx[i] y[i]=y[i]+dy[i] def testCollision(i): global x,y,width,height,r,dx,dy,ry,rh,rw #bords verticaux if x[i]+r[i] > width or x[i]-r[i] 0: dx[i]=-dx[i] #bords horizontaux if y[i]+r[i] > height or y[i]-r[i] < 0: dy[i]=-dy[i] if (ry < y[i]) and (y[i] < (ry + rh)) and ((x[i] - r[i]) < (rx + rw)): dx[i]=-dx[i] def testEvenements(): for event in pygame.event.get(): if event.type == pygame.QUIT:#si clique sur la croix quitter pygame.display.quit()#ferme la fenĂȘtre sys.exit()#arrĂȘte le programme if event.type == KEYDOWN: bouger_raquette() #fonctions de la raquette def afficher_raquette(): rect(screen, rcolor, [rx, ry, rw, rh]) def bouger_raquette(): global ry, dry if pygame.key.get_pressed()[K_UP]: ry-=dry if pygame.key.get_pressed()[K_DOWN]: ry+=dry #lancement des fonctionnalitĂ©s de la librairie pygame pygame.init() #vĂ©rifier les interactions clavier toutes les 10ms pygame.key.set_repeat(10, 10) #affichage d'une fenĂȘtre de dessin de largeur 500 pixels et de hauteur 500 pixels screen = set_mode(size) while True: #remplissage du fond par la couleur blanche screen.fill(couleurFond) for i in range(0,N): #afficher la balle : afficher(i) #dĂ©placement de la balle : avancer(i) #test de collision testCollision(i) afficher_raquette() flip()#activer le rendu graphique pygame.time.delay(15)#une image toute les 15 ms #test evenements, arrĂȘt de jeu : testEvenements() code source : pong3.1.py

Le pong réalisé est ainsi jouable. Il ne s'agit bien sûr pas d'un jeu finalisé. Il nous aura permis d'introduire toutes les notions fondamentales de programmation python ainsi que des morceaux de code réutilisables pour d'autres types de projets.

Il est possible de poursuivre et d'améliorer le jeu :

>